package com.sn.author.filter.interceptor;
import com.sn.author.common.annotation.IgnoreToken;
import com.sn.author.common.context.JwtTokenHelper;
import com.sn.author.common.context.SessionHelper;
import com.sn.author.common.exception.AException;
import com.sn.author.common.exception.HeaderException;
import com.sn.author.common.exception.NoPermissionException;
import com.sn.author.filter.ApiRequestSupport;
import com.sn.author.filter.authentication.AuthenticationImpl;
import com.sn.author.filter.content.SecurityContextHolder;
import com.sn.author.filter.content.SecurityContextImpl;
import com.sn.author.filter.content.UserDetail;
import com.sn.author.service.dao.UserService;
import com.sn.author.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;

/**
 * Request permission valid.
 */
@Configuration
@Slf4j
public class RequestValidInterceptor extends HandlerInterceptorAdapter {

    private final UserService userService;

    public RequestValidInterceptor(UserService userService) {
        this.userService = userService;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try {
            if (handler instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                IgnoreToken ignoreToken = handlerMethod.getMethod().getAnnotation(IgnoreToken.class);
                if(ignoreToken != null){
                    return true;
                }
                //权限验证,解析JWT
                String token = SessionHelper.getRequestToken();
//                String token = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJjaGVuIiwiZXhwIjoxNjA1NjE4OTM3fQ.psiFIAQKu76g9exjPlNRc_8mDNNUSLSSVne5YztQGFfTaTg2pK4UIV5MFLW4U45Xsy92zGuaCeCdOD95ev9w5Q";
                if(StringUtils.isBlank(token)){
                    throw new HeaderException("Please login again.");
                }


                String username = JwtTokenHelper.getUsernameFromToken(token);
                if(StringUtils.isBlank(username)){
                    throw new NoPermissionException("Authentication failed");
                }

                if(JwtTokenHelper.isTokenExpired(token)){
                    throw new NoPermissionException("Token has expired.");
                }

                Optional<UserDetail> optUser = userService.getUserDetail(username);

                if(!optUser.isPresent()){
                    throw new NoPermissionException("Account does not exist or has been disabled");
                }

                if(!JwtTokenHelper.validateToken(token, optUser.get())){
                    throw new NoPermissionException("Token expired or has expired");
                }
                log.info("Request valid passed   <<<<<<<<<<>>>>>>>>>>>>>>   username:[{}] expireDate:[{}]",username, DateUtils.formatYMDHMS(JwtTokenHelper.getExpirationDateFromToken(token)));

                SecurityContextImpl context = optUser
                        .map(userDetail -> new SecurityContextImpl(new AuthenticationImpl(userDetail)))
                        .orElseThrow(() -> new NoPermissionException("Token parser failed. Please login again."));

                // Set security
                SecurityContextHolder.setContext(context);
            }
        }catch (AException e){
            log.error("Interceptor throw exception : " + "\t" + e.getMessage());
            ApiRequestSupport.invokeExceptionWrapper(response, e.getCode(),e.getMessage());
            return false;
        }
        return true;
    }
}
